#!/bin/bash
###############################################################################
#       脚本名称: utils_character.sh
#       功能描述: 字符串工具类功能函数，提供纯粹的字符串处理功能。
#       作者: 林再来
#       日期: 2025-10-20
#       版本: 1.0
#       功能:
#           1、编码检测与转换(gbk/utf-8/unicode)   
#           2、汉字特性处理(是否汉字/是否全角/是否半角/是否数字/是否字母/是否符号)
#           3、字符串格式化(截取/替换/删除/插入/拼接/反转/大小写转换)
#           4、字符串清理(去除空格/换行/tab/空字符/重复字符)
#           5、字符串验证(长度检查/格式验证/字符类型检查)
#           6、正则表达式工具(匹配/替换/提取)
#       依赖(插件/命令):
#           1、bash
#           2、iconv
#           3、awk
#           4、sed
#           5、grep
###############################################################################

# 防止重复加载
if [[ -n "${utils_character_sh_loaded:-}" ]]; then
    return 0
fi
readonly utils_character_sh_loaded=1

# 注意：不使用严格模式，避免影响交互式 shell

# 获取脚本目录和项目根目录（如果尚未定义）
if [[ -z "${script_dir:-}" ]]; then
    script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    readonly script_dir
fi

if [[ -z "${project_root:-}" ]]; then
    project_root="$(cd "${script_dir}/../.." && pwd)"
    readonly project_root
fi

###############################################################################
# 全局常量
###############################################################################

# 字符类型常量
readonly UTILS_CHAR_TYPE_LETTER="letter"
readonly UTILS_CHAR_TYPE_DIGIT="digit"
readonly UTILS_CHAR_TYPE_SYMBOL="symbol"
readonly UTILS_CHAR_TYPE_SPACE="space"
readonly UTILS_CHAR_TYPE_CHINESE="chinese"
readonly UTILS_CHAR_TYPE_ALPHANUMERIC="alphanumeric"

# 编码类型常量
readonly UTILS_ENCODING_UTF8="utf-8"
readonly UTILS_ENCODING_GBK="gbk"
readonly UTILS_ENCODING_ASCII="ascii"

###############################################################################
# 编码检测与转换函数
###############################################################################

# 函数: 检测字符串编码
# 参数: $1 - 字符串
# 返回: 编码类型
# 说明: 检测字符串的编码类型
function utils_character_detect_encoding() {
    local input="$1"
    
    if [[ -z "$input" ]]; then
        echo "$UTILS_ENCODING_ASCII"
        return 0
    fi
    
    # 使用file命令检测编码
    if command -v file >/dev/null 2>&1; then
        local encoding=$(echo "$input" | file -bi - | grep -o 'charset=[^;]*' | cut -d= -f2)
        echo "${encoding:-$UTILS_ENCODING_UTF8}"
    else
        # 简单检测：如果包含非ASCII字符，假设为UTF-8
        if [[ "$input" =~ [^\x00-\x7F] ]]; then
            echo "$UTILS_ENCODING_UTF8"
        else
            echo "$UTILS_ENCODING_ASCII"
        fi
    fi
}

# 函数: 转换字符串编码
# 参数: $1 - 输入字符串, $2 - 源编码, $3 - 目标编码
# 返回: 转换后的字符串
# 说明: 转换字符串的编码格式
function utils_character_convert_encoding() {
    local input="$1"
    local from_encoding="${2:-$UTILS_ENCODING_UTF8}"
    local to_encoding="${3:-$UTILS_ENCODING_UTF8}"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    if [[ "$from_encoding" == "$to_encoding" ]]; then
        echo "$input"
        return 0
    fi
    
    # 使用iconv进行编码转换
    if command -v iconv >/dev/null 2>&1; then
        echo "$input" | iconv -f "$from_encoding" -t "$to_encoding" 2>/dev/null || echo "$input"
    else
        echo "$input"
    fi
}

###############################################################################
# 字符类型检测函数
###############################################################################

# 函数: 检测字符类型
# 参数: $1 - 字符
# 返回: 字符类型
# 说明: 检测单个字符的类型
function utils_character_get_type() {
    local char="$1"
    
    if [[ -z "$char" ]]; then
        echo "$UTILS_CHAR_TYPE_SPACE"
        return 0
    fi
    
    # 只取第一个字符
    char="${char:0:1}"
    
    # 检测中文字符
    if [[ "$char" =~ [\u4e00-\u9fff] ]]; then
        echo "$UTILS_CHAR_TYPE_CHINESE"
    # 检测字母
    elif [[ "$char" =~ [a-zA-Z] ]]; then
        echo "$UTILS_CHAR_TYPE_LETTER"
    # 检测数字
    elif [[ "$char" =~ [0-9] ]]; then
        echo "$UTILS_CHAR_TYPE_DIGIT"
    # 检测空格
    elif [[ "$char" =~ [[:space:]] ]]; then
        echo "$UTILS_CHAR_TYPE_SPACE"
    # 其他为符号
    else
        echo "$UTILS_CHAR_TYPE_SYMBOL"
    fi
}

# 函数: 检查是否为中文字符
# 参数: $1 - 字符
# 返回: 0-是中文, 1-不是中文
# 说明: 检查字符是否为中文字符
function utils_character_is_chinese() {
    local char="$1"
    [[ "$char" =~ [\u4e00-\u9fff] ]]
}

# 函数: 检查是否为字母
# 参数: $1 - 字符
# 返回: 0-是字母, 1-不是字母
# 说明: 检查字符是否为字母
function utils_character_is_letter() {
    local char="$1"
    [[ "$char" =~ [a-zA-Z] ]]
}

# 函数: 检查是否为数字
# 参数: $1 - 字符
# 返回: 0-是数字, 1-不是数字
# 说明: 检查字符是否为数字
function utils_character_is_digit() {
    local char="$1"
    [[ "$char" =~ [0-9] ]]
}

# 函数: 检查是否为字母数字
# 参数: $1 - 字符
# 返回: 0-是字母数字, 1-不是字母数字
# 说明: 检查字符是否为字母或数字
function utils_character_is_alphanumeric() {
    local char="$1"
    [[ "$char" =~ [a-zA-Z0-9] ]]
}

###############################################################################
# 字符串格式化函数
###############################################################################

# 函数: 截取字符串
# 参数: $1 - 输入字符串, $2 - 起始位置, $3 - 长度（可选）
# 返回: 截取后的字符串
# 说明: 截取字符串的指定部分
function utils_character_substring() {
    local input="$1"
    local start="$2"
    local length="${3:-}"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    if [[ -n "$length" ]]; then
        echo "${input:$start:$length}"
    else
        echo "${input:$start}"
    fi
}

# 函数: 替换字符串
# 参数: $1 - 输入字符串, $2 - 查找字符串, $3 - 替换字符串
# 返回: 替换后的字符串
# 说明: 替换字符串中的指定内容
function utils_character_replace() {
    local input="$1"
    local search="$2"
    local replace="$3"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    echo "${input//$search/$replace}"
}

# 函数: 删除字符串中的指定内容
# 参数: $1 - 输入字符串, $2 - 要删除的字符串
# 返回: 删除后的字符串
# 说明: 删除字符串中的指定内容
function utils_character_remove() {
    local input="$1"
    local remove="$2"
    
    utils_character_replace "$input" "$remove" ""
}

# 函数: 反转字符串
# 参数: $1 - 输入字符串
# 返回: 反转后的字符串
# 说明: 反转字符串的顺序
function utils_character_reverse() {
    local input="$1"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    # 使用rev命令（如果可用）
    if command -v rev >/dev/null 2>&1; then
        echo "$input" | rev
    else
        # 手动反转
        local result=""
        local len=${#input}
        for ((i=len-1; i>=0; i--)); do
            result="${result}${input:$i:1}"
        done
        echo "$result"
    fi
}

# 函数: 转换为小写
# 参数: $1 - 输入字符串
# 返回: 小写字符串
# 说明: 将字符串转换为小写
function utils_character_to_lower() {
    local input="$1"
    echo "${input,,}"
}

# 函数: 转换为大写
# 参数: $1 - 输入字符串
# 返回: 大写字符串
# 说明: 将字符串转换为大写
function utils_character_to_upper() {
    local input="$1"
    echo "${input^^}"
}

# 函数: 首字母大写
# 参数: $1 - 输入字符串
# 返回: 首字母大写的字符串
# 说明: 将字符串的首字母转换为大写
function utils_character_capitalize() {
    local input="$1"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    local first="${input:0:1}"
    local rest="${input:1}"
    echo "$(utils_character_to_upper "$first")$rest"
}

###############################################################################
# 字符串清理函数
###############################################################################

# 函数: 去除首尾空格
# 参数: $1 - 输入字符串
# 返回: 去除空格后的字符串
# 说明: 去除字符串首尾的空格
function utils_character_trim() {
    local input="$1"
    local trimmed="${input#"${input%%[![:space:]]*}"}"
    trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"
    echo "$trimmed"
}

# 函数: 去除所有空格
# 参数: $1 - 输入字符串
# 返回: 去除空格后的字符串
# 说明: 去除字符串中的所有空格
function utils_character_remove_spaces() {
    local input="$1"
    utils_character_replace "$input" " " ""
}

# 函数: 去除换行符
# 参数: $1 - 输入字符串
# 返回: 去除换行符后的字符串
# 说明: 去除字符串中的换行符
function utils_character_remove_newlines() {
    local input="$1"
    utils_character_replace "$input" $'\n' ""
}

# 函数: 去除制表符
# 参数: $1 - 输入字符串
# 返回: 去除制表符后的字符串
# 说明: 去除字符串中的制表符
function utils_character_remove_tabs() {
    local input="$1"
    utils_character_replace "$input" $'\t' ""
}

# 函数: 去除所有空白字符
# 参数: $1 - 输入字符串
# 返回: 去除空白字符后的字符串
# 说明: 去除字符串中的所有空白字符（空格、制表符、换行符等）
function utils_character_remove_whitespace() {
    local input="$1"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    # 使用sed去除所有空白字符
    if command -v sed >/dev/null 2>&1; then
        echo "$input" | sed 's/[[:space:]]//g'
    else
        # 手动处理
        local result="$input"
        result=$(utils_character_remove_spaces "$result")
        result=$(utils_character_remove_tabs "$result")
        result=$(utils_character_remove_newlines "$result")
        echo "$result"
    fi
}

# 函数: 去除重复字符
# 参数: $1 - 输入字符串, $2 - 字符（可选，默认去除所有重复字符）
# 返回: 去除重复字符后的字符串
# 说明: 去除字符串中的重复字符
function utils_character_remove_duplicates() {
    local input="$1"
    local char="${2:-}"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    if [[ -n "$char" ]]; then
        # 去除指定字符的重复
        local result=""
        local prev=""
        for ((i=0; i<${#input}; i++)); do
            local current="${input:$i:1}"
            if [[ "$current" != "$char" ]] || [[ "$current" != "$prev" ]]; then
                result="${result}${current}"
            fi
            prev="$current"
        done
        echo "$result"
    else
        # 去除所有重复字符
        local result=""
        local prev=""
        for ((i=0; i<${#input}; i++)); do
            local current="${input:$i:1}"
            if [[ "$current" != "$prev" ]]; then
                result="${result}${current}"
            fi
            prev="$current"
        done
        echo "$result"
    fi
}

###############################################################################
# 字符串验证函数
###############################################################################

# 函数: 检查字符串长度
# 参数: $1 - 输入字符串, $2 - 最小长度, $3 - 最大长度（可选）
# 返回: 0-长度符合, 1-长度不符合
# 说明: 检查字符串长度是否在指定范围内
function utils_character_check_length() {
    local input="$1"
    local min_length="$2"
    local max_length="${3:-}"
    
    local length=${#input}
    
    if [[ $length -lt $min_length ]]; then
        return 1
    fi
    
    if [[ -n "$max_length" ]] && [[ $length -gt $max_length ]]; then
        return 1
    fi
    
    return 0
}

# 函数: 检查字符串是否为空
# 参数: $1 - 输入字符串
# 返回: 0-为空, 1-不为空
# 说明: 检查字符串是否为空
function utils_character_is_empty() {
    local input="$1"
    [[ -z "$input" ]]
}

# 函数: 检查字符串是否只包含字母
# 参数: $1 - 输入字符串
# 返回: 0-只包含字母, 1-包含其他字符
# 说明: 检查字符串是否只包含字母
function utils_character_is_alpha_only() {
    local input="$1"
    [[ "$input" =~ ^[a-zA-Z]+$ ]]
}

# 函数: 检查字符串是否只包含数字
# 参数: $1 - 输入字符串
# 返回: 0-只包含数字, 1-包含其他字符
# 说明: 检查字符串是否只包含数字
function utils_character_is_digit_only() {
    local input="$1"
    [[ "$input" =~ ^[0-9]+$ ]]
}

# 函数: 检查字符串是否只包含字母数字
# 参数: $1 - 输入字符串
# 返回: 0-只包含字母数字, 1-包含其他字符
# 说明: 检查字符串是否只包含字母和数字
function utils_character_is_alphanumeric_only() {
    local input="$1"
    [[ "$input" =~ ^[a-zA-Z0-9]+$ ]]
}

###############################################################################
# 正则表达式工具函数
###############################################################################

# 函数: 正则表达式匹配
# 参数: $1 - 输入字符串, $2 - 正则表达式
# 返回: 0-匹配, 1-不匹配
# 说明: 检查字符串是否匹配正则表达式
function utils_character_regex_match() {
    local input="$1"
    local pattern="$2"
    [[ "$input" =~ $pattern ]]
}

# 函数: 正则表达式替换
# 参数: $1 - 输入字符串, $2 - 正则表达式, $3 - 替换字符串
# 返回: 替换后的字符串
# 说明: 使用正则表达式替换字符串
function utils_character_regex_replace() {
    local input="$1"
    local pattern="$2"
    local replacement="$3"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    # 使用sed进行正则替换
    if command -v sed >/dev/null 2>&1; then
        echo "$input" | sed -E "s/$pattern/$replacement/g"
    else
        # 简单替换（不支持复杂正则）
        echo "$input"
    fi
}

# 函数: 提取匹配的字符串
# 参数: $1 - 输入字符串, $2 - 正则表达式
# 返回: 匹配的字符串
# 说明: 提取字符串中匹配正则表达式的部分
function utils_character_regex_extract() {
    local input="$1"
    local pattern="$2"
    
    if [[ -z "$input" ]]; then
        echo ""
        return 0
    fi
    
    if [[ "$input" =~ $pattern ]]; then
        echo "${BASH_REMATCH[0]}"
    else
        echo ""
    fi
}

###############################################################################
# 统计函数
###############################################################################

# 函数: 统计字符数量
# 参数: $1 - 输入字符串, $2 - 字符类型（可选）
# 返回: 字符数量
# 说明: 统计字符串中指定类型字符的数量
function utils_character_count() {
    local input="$1"
    local char_type="${2:-all}"
    
    if [[ -z "$input" ]]; then
        echo "0"
        return 0
    fi
    
    case "$char_type" in
        "letter")
            echo "$input" | grep -o '[a-zA-Z]' | wc -l
            ;;
        "digit")
            echo "$input" | grep -o '[0-9]' | wc -l
            ;;
        "chinese")
            echo "$input" | grep -o '[\u4e00-\u9fff]' | wc -l
            ;;
        "space")
            echo "$input" | grep -o '[[:space:]]' | wc -l
            ;;
        "symbol")
            echo "$input" | grep -o '[^a-zA-Z0-9[:space:]]' | wc -l
            ;;
        *)
            echo "${#input}"
            ;;
    esac
}